package middleware

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/fatih/color"
	"github.com/gin-gonic/gin"
)

// Middleware 中间件函数类型
type Middleware func(http.HandlerFunc) http.HandlerFunc

// Chain 中间件链
func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc {
	// 从后向前包装
	for i := len(middlewares) - 1; i >= 0; i-- {
		f = middlewares[i](f)
	}
	return f
}

// Logging 日志中间件
func Logging(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		next(w, r)
		log.Printf("[%s] %s %s %v", r.Method, r.URL.Path, r.RemoteAddr, time.Since(start))
	}
}

// RecoveryHandler 恢复中间件
func RecoveryHandler(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if err := recover(); err != nil {
				log.Printf("Panic recovered: %v", err)
				http.Error(w, "Internal Server Error", http.StatusInternalServerError)
			}
		}()
		next(w, r)
	}
}

// Cors 中间件用于处理跨域请求
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}

		c.Next()
	}
}

// Logger 中间件用于记录请求日志（带颜色）
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 开始时间
		start := time.Now()
		path := c.Request.URL.Path
		raw := c.Request.URL.RawQuery

		// 处理请求
		c.Next()

		// 结束时间
		end := time.Now()
		latency := end.Sub(start)

		// 获取状态码
		statusCode := c.Writer.Status()
		clientIP := c.ClientIP()
		method := c.Request.Method

		// 根据请求方法选择颜色
		var methodColor *color.Color
		switch method {
		case "GET":
			methodColor = color.New(color.FgGreen)
		case "POST":
			methodColor = color.New(color.FgBlue)
		case "PUT":
			methodColor = color.New(color.FgYellow)
		case "DELETE":
			methodColor = color.New(color.FgRed)
		default:
			methodColor = color.New(color.FgWhite)
		}

		// 根据状态码选择颜色
		var statusColor *color.Color
		switch {
		case statusCode >= 200 && statusCode < 300:
			statusColor = color.New(color.FgGreen)
		case statusCode >= 300 && statusCode < 400:
			statusColor = color.New(color.FgYellow)
		case statusCode >= 400:
			statusColor = color.New(color.FgRed)
		default:
			statusColor = color.New(color.FgWhite)
		}

		// 构建日志信息
		if raw != "" {
			path = path + "?" + raw
		}

		// 打印带颜色的日志
		fmt.Printf("[GIN] %v | %s | %s | %s | %s | %v\n",
			end.Format("2006/01/02 - 15:04:05"),
			methodColor.Sprint(method),
			path,
			clientIP,
			statusColor.Sprintf("%d", statusCode),
			latency,
		)
	}
}

// Recovery 中间件用于从 panic 中恢复
func Recovery() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				// 使用红色显示错误信息
				errorColor := color.New(color.FgRed)
				fmt.Printf("%s [PANIC] %s | %s | Panic: %v\n",
					errorColor.Sprint(time.Now().Format("2006/01/02 - 15:04:05")),
					c.Request.URL.Path,
					c.ClientIP(),
					err,
				)

				// 返回 500 错误
				c.JSON(500, gin.H{
					"code":    500,
					"message": "Internal Server Error",
				})
				c.Abort()
			}
		}()
		c.Next()
	}
}
